#include "buzzer.h"
#include <avr/interrupt.h>

#define BUZZER_PORT PORTC
#define BUZZER_DDR DDRC
#define BUZZER_PIN PC5

//TIEMPO DE NOTAS MUSICALES, CALCULADAS A PARTIR DE LA FRECUENCIA DE CADA NOTA. SERIA ((1/FREQ) * 1000000)/ 2
#define DO3_NOTE_US 1911 * (F_CPU/1000000)
#define RE3_NOTE_US 1703 * (F_CPU/1000000)
#define MI3_NOTE_US 1517 * (F_CPU/1000000)
#define FA3_NOTE_US 1351 * (F_CPU/1000000)
#define SOL3_NOTE_US 1275 * (F_CPU/1000000)
#define LA3_NOTE_US 1136 * (F_CPU/1000000)
#define SI3_NOTE_US 1012 * (F_CPU/1000000)

#define DO4_NOTE_US 956 * (F_CPU/1000000)
#define RE4_NOTE_US 851 * (F_CPU/1000000)
#define MI4_NOTE_US 759 * (F_CPU/1000000)
#define FA4_NOTE_US 716 * (F_CPU/1000000)
#define SOL4_NOTE_US 638 * (F_CPU/1000000)
#define LA4_NOTE_US 568 * (F_CPU/1000000)
#define SI4_NOTE_US 506 * (F_CPU/1000000)

#define DO5_NOTE_US 478 * (F_CPU/1000000)
#define RE5_NOTE_US 426 * (F_CPU/1000000)
#define MI5_NOTE_US 379 * (F_CPU/1000000)
#define FA5_NOTE_US 338 * (F_CPU/1000000)
#define SOL5_NOTE_US 301 * (F_CPU/1000000)
#define LA5_NOTE_US 268 * (F_CPU/1000000)
#define SI5_NOTE_US 253 * (F_CPU/1000000)

//function prototypes
static void timer4_init(void);

void buzzer_init(void)
{
	timer4_init();
	
}


static void timer4_init()
{
	TCCR4B |= (1<<WGM42);
	TIMSK4 |= (1<<OCIE4A);
}

void buzzer_disable()
{
	BUZZER_DDR &= ~(1<<BUZZER_PIN);
	TCCR4B &= ~(1<<CS40);
}

void buzzer_enable()
{
	BUZZER_DDR |= (1<<BUZZER_PIN);
	TCCR4B |= (1<<CS40);
}


void buzzer_note(unsigned char note)
{
	buzzer_enable();
	switch(note)
	{
		case DO1:
		OCR4A = DO3_NOTE_US;
		break;
		case RE1:
		OCR4A = RE3_NOTE_US;
		break;
		case MI1:
		OCR4A = MI3_NOTE_US;
		break;
		case FA1:
		OCR4A = FA3_NOTE_US;
		break;
		case SOL1:
		OCR4A = SOL3_NOTE_US;
		break;
		case LA1:
		OCR4A = LA3_NOTE_US;
		break;
		case SI1:
		OCR4A = SI3_NOTE_US;
		break;

		case DO2:
		OCR4A = DO4_NOTE_US;
		break;
		case RE2:
		OCR4A = RE4_NOTE_US;
		break;
		case MI2:
		OCR4A = MI4_NOTE_US;
		break;
		case FA2:
		OCR4A = FA4_NOTE_US;
		break;
		case SOL2:
		OCR4A = SOL4_NOTE_US;
		break;
		case LA2:
		OCR4A = LA4_NOTE_US;
		break;
		case SI2:
		OCR4A = SI4_NOTE_US;
		break;

		case DO3:
		OCR4A = DO5_NOTE_US;
		break;
		case RE3:
		OCR4A = RE5_NOTE_US;
		break;
		case MI3:
		OCR4A = MI5_NOTE_US;
		break;
		case FA3:
		OCR4A = FA5_NOTE_US;
		break;
		case SOL3:
		OCR4A = SOL5_NOTE_US;
		break;
		case LA3:
		OCR4A = LA5_NOTE_US;
		break;
		case SI3:
		OCR4A = SI5_NOTE_US;
		break;
		
		case SILENCE:
		buzzer_disable();
		break;
	}

}

//funcion de interrupcion que hace parte de la libreria de buzzer
ISR(TIMER4_COMPA_vect)
{
	static unsigned char state = 0;
	
	if(state)
	{
		BUZZER_PORT |= (1<<BUZZER_PIN);
		state = 0;
	}
	else
	{
		BUZZER_PORT &= ~(1<<BUZZER_PIN);
		state = 1;
	}
	
}
